package haois.module.traffic.rest;


import haois.constant.ReturnState;
import haois.security.HandleCookie;
import haois.module.traffic.daomain.Traffic;
import haois.module.navigate.daomain.WebSite;
import haois.module.navigate.service.WebSiteService;
import haois.module.traffic.service.TrafficService;
import haois.constant.NetworkUtil;
import haois.constant.CommonConstants;
import haois.util.GetAddByIp;
import haois.constant.Reply;
import haois.util.RespUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;



/**
 * Created by haol on 2017/4/22.
 */
@RestController
@RequestMapping("/record")
public class TrafficController {

    private Logger logger = LoggerFactory.getLogger(TrafficController.class);
    @Autowired
    private TrafficService trafficService;
    @Autowired
    private WebSiteService webSiteService;


    /**
     * @api JS DEMO
     * @apiGroup Traffic
     * @apiName demo
     * @apiDescription 请访问 <a href ="http://www.haol.site/index/demo.js">SeeDemo</a> 查看demo文件
     * @apiParamExample {json} 请求样例：
     * http://www.haol.site/index/demo.js
     */

    /**
     * @api {POST} /record/add/{appId} 增加访问记录
     * @apiGroup Traffic
     * @apiName addRecord
     * @apiDescription 增加一个站访问记录
     * @apiParam {String} appId 网页名
     * @apiParam {String} fromPage/appKey 来源/关键字
     * @apiParamExample {json} 请求样例：
     * POST /record/add/{appId}
     * @apiSuccessExample {json} 返回样例:
     * {"true"}
     */
    @RequestMapping(value = "/add/{appId}", method = RequestMethod.POST)
    public String addRecord(@PathVariable String appId, String fromPage, String pageKey,
                            HttpServletRequest request, HttpServletResponse response) {
        RespUtil.setACAO(response);
        Traffic traffic = new Traffic();
        try {
            if (appId == null) {
                appId = CommonConstants.COOK_NAME;
            }
            WebSite webSite = webSiteService.getByAppId(appId);
            if (webSite == null) {
                return new Reply(ReturnState.CODE_13, "appId不正确").toJson();
            }
            traffic.setAppId(appId);
            traffic.setWebId(webSite.getId());
            traffic.setPageKey(pageKey);
            traffic.setIp(NetworkUtil.getIpAddress(request));
            traffic.setFromPage(fromPage);
            traffic.setAddress(GetAddByIp.getAddressByIP(traffic.getIp()));

            if (trafficService.checkIsIgnore(traffic.getIp(), "#")) {
                logger.info("IP地址为[{}]的访客访问[{}],已被标记为内部人员,不计数",
                        traffic.getIp(), appId);
                return new Reply(ReturnState.CODE_06, "访客为内部人员").toJson();
            }
            if (trafficService.checkIsIgnore(traffic.getIp(), appId)) {
                logger.info("IP地址为[{}]的访客访问[{}],已被标记为网站管理员,不计数",
                        traffic.getIp(), appId);
                trafficService.addNeglect(appId);
                return new Reply(ReturnState.CODE_06, "访客为管理员").toJson();
            }
            try {
                Cookie cookie = HandleCookie.getCookieByName(request, appId);
                if (cookie != null) {
                    logger.info("IP地址为[{}],地理位置为[{}]的访客,刚刚已经访问页面[{}]，本次忽略",
                            traffic.getIp(), GetAddByIp.getAddressByIP(traffic.getIp()), traffic.getAppId());
                    return new Reply(ReturnState.CODE_06, "短时间多次访问，不记录").toJson();
                }
            } catch (NullPointerException e) {
                HandleCookie.saveCookie(response, appId, CommonConstants.COOK_VALUE);
                trafficService.addRecord(traffic);
                logger.info("IP地址为[{}]，地理位置为[{}]的访客访问了页面[{}]",
                        traffic.getIp(), GetAddByIp.getAddressByIP(traffic.getIp()), traffic.getAppId());
            }
            return new Reply(ReturnState.CODE_00, "你是第" + webSite.getCount() + "位访客").toJson();
        } catch (Exception e) {
            e.printStackTrace();
            return new Reply(ReturnState.CODE_10, "记录失败:" + e.getMessage()).toJson();
        }

    }

    /**
     * @api {POST} /record/del 删除网站的访问记录
     * @apiGroup Traffic
     * @apiName clearRecord
     * @apiDescription 删除网站的访问记录，但不删除网站的浏览数量
     * @apiParam {String} appId 网站id
     * @apiParam {String} appSecret 网站密码
     * @apiParam {String} ip 需要删除的浏览记录的ip，不填则为全部
     * @apiParamExample {json} 请求样例：
     * POST /record/del/{appId}
     * @apiSuccessExample {json} 返回样例:
     * {"true"}
     */
    @RequestMapping(value = "/del/{appId}", method = RequestMethod.POST, params = {"appSecret"})
    public String clearRecord(@PathVariable String appId, String appSecret, String ip, HttpServletResponse response) {
        RespUtil.setACAO(response);
        WebSite webSite = webSiteService.getByAppId(appId);
        if (webSite == null) {
            return new Reply(ReturnState.CODE_02, "网站未找到").toJson();
        }
        if (!webSite.getAppSecret().equals(appSecret)) {
            return new Reply(ReturnState.CODE_13, "appSecret不正确").toJson();
        }
        if (ip != null) {
            trafficService.deleteRecord(webSite.getAppId(), ip);
        } else {
            trafficService.deleteRecord(webSite.getAppId());
        }
        return new Reply(ReturnState.CODE_00, "删除成功").toJson();
    }

    /**
     * @api {GET} /record/see 查看全部访问记录
     * @apiGroup Traffic
     * @apiName getRecord
     * @apiDescription 查看全部访问记录
     * @apiParamExample {json} 请求样例：
     * GET /record/see
     * @apiSuccessExample {json} 返回样例:
     * {"code":0,"msg":"success","data":[{"id":159,"softId":0,"ip":"120.236.146.233","come":"home","time":"2017-04-29 23:16:59"},{"id":160,"softId":0,"ip":"199.30.24.229","come":"home","time":"2017-05-02 07:37:21"},{"id":177,"softId":0,"ip":"140.205.201.9","come":"home","time":"2017-05-03 08:26:56"},{"id":194,"softId":0,"ip":"140.205.201.18","come":"home","time":"2017-05-06 06:54:51"},{"id":223,"softId":0,"ip":"131.253.25.133","come":"home","time":"2017-05-08 02:59:35"},{"id":322,"softId":0,"ip":"123.7.178.153","come":"home","time":"2017-05-12 15:03:34"}]}
     */
    @RequestMapping(value = "/list")
    public String getRecord(HttpServletResponse response) {
        RespUtil.setACAO(response);
        List<Traffic> traffic = trafficService.getRecord();
        Reply<List<Traffic>> reply = new Reply<List<Traffic>>(ReturnState.CODE_00, "success", traffic);
        return reply.toJson();
    }

    /**
     * @api {GET} /record/see/{id}  获取访问记录ById
     * @apiGroup Traffic
     * @apiName getRecordById
     * @apiDescription 根据{id}获取该条访问记录的详细信息
     * @apiParam {Integer} id 网页id
     * @apiParamExample {json} 请求样例：
     * GET /record/see/1
     * @apiSuccessExample {json} 返回样例:
     * {"code":0,"msg":"success","data":{"id":159,"softId":0,"ip":"120.236.146.233","come":"home","time":"2017-04-29 23:16:59"}}
     */
    @RequestMapping(value = "/see/{id}")
    public String getRecordById(@PathVariable int id, HttpServletResponse response) {
        RespUtil.setACAO(response);
        Traffic traffic = trafficService.getRecord(id);
        Reply<Traffic> reply = new Reply<Traffic>(ReturnState.CODE_00, "success", traffic);
        return reply.toJson();
    }

    /**
     * @api {GET} /record/list/{appId}  全部浏览记录byAppId
     * @apiGroup Traffic
     * @apiName record
     * @apiDescription 根据appId获取该网站的全部浏览记录
     * @apiParam {Integer} id 网站id
     * @apiParamExample {json} 请求样例：
     * GET /record/list/{appId}
     * @apiSuccessExample {json} 返回样例:
     * {"code":0,"msg":"success","data":[{"id":159,"softId":0,"ip":"120.236.146.233","come":"home","time":"2017-04-29 23:16:59"},{"id":160,"softId":0,"ip":"199.30.24.229","come":"home","time":"2017-05-02 07:37:21"},{"id":177,"softId":0,"ip":"140.205.201.9","come":"home","time":"2017-05-03 08:26:56"},{"id":194,"softId":0,"ip":"140.205.201.18","come":"home","time":"2017-05-06 06:54:51"},{"id":223,"softId":0,"ip":"131.253.25.133","come":"home","time":"2017-05-08 02:59:35"},{"id":322,"softId":0,"ip":"123.7.178.153","come":"home","time":"2017-05-12 15:03:34"}]}
     */
    @RequestMapping(value = "/list/{appId}")
    public String record(@PathVariable String appId, HttpServletResponse response) {
        RespUtil.setACAO(response);
        WebSite webSite = webSiteService.getByAppId(appId);
        List<Traffic> traffic = null;
        if (webSite != null) {
            traffic = trafficService.getRecordByAppId(appId);
        }
        Reply<List<Traffic>> reply = new Reply<List<Traffic>>(ReturnState.CODE_00, "success", traffic);
        return reply.toJson();
    }

    /**
     * @api {GET} /location/{ip} 普通IP定位API服务
     * @apiGroup Traffic
     * @apiName location
     * @apiDescription 位置数据（包括经纬度信息、地址信息等）
     * @apiParam {String} ip IP地址
     * @apiParamExample {json} 请求样例：
     * GET /trans/{ip}
     * @apiSuccessExample {json} 返回样例:
     * {
     * address: "CN|北京|北京|None|CHINANET|1|None",    #地址
     * content:    #详细内容
     * {
     * address: "北京市",    #简要地址
     * address_detail:    #详细地址信息
     * {
     * city: "北京市",    #城市
     * city_code: 131,    #百度城市代码
     * district: "",    #区县
     * province: "北京市",    #省份
     * street: "",    #街道
     * street_number: ""    #门址
     * },
     * point:    #当前城市中心点，注意当前坐标返回类型
     * {
     * x: "116.39564504",
     * y: "39.92998578"
     * }
     * },
     * status: 0    #返回状态码
     * }
     */
    @RequestMapping(value = "/location/{ip:.+}")
    public String location(@PathVariable String ip, HttpServletRequest request) {
        if (ip.equals("127.0.0.1")) {
            ip = NetworkUtil.getIpAddress(request);
        }
        String addr = GetAddByIp.transferByIp(ip);
        Map map = new HashMap();
        map.put("Ip", ip);
        map.put("Addr", addr);
        return addr;
    }
}
